﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Microsoft.Synchronization.Data;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Diagnostics;

namespace SyncLib
{
    [DataContract]
    public class KSyncStatistics : IDisposable
    {
        [DataMember]
        public Guid SessionId { get; set; }
        [DataMember]
        public DbSyncScopeProgress ScopeProcess { get; set; }
        [DataMember]
        public Dictionary<string, List<KSyncConflict>> ConflictDatas { get; set; }
        [DataMember]
        public Dictionary<string, DbSyncScopeProgress> DependencyStatistic { get; set; }
        ~KSyncStatistics()
        {
            ConflictDatas.Clear();
        }
        #region IDisposable Members

        public void Dispose()
        {

            ConflictDatas.Clear();
        }

        #endregion
        public void CheckValue()
        {
            if (SessionId.Equals(Guid.Empty))
                SessionId = Guid.NewGuid();
            if (ScopeProcess == null)
                ScopeProcess = new DbSyncScopeProgress();
            if (ConflictDatas == null)
                ConflictDatas = new Dictionary<string, List<KSyncConflict>>();
            if (DependencyStatistic == null)
                DependencyStatistic = new Dictionary<string, DbSyncScopeProgress>();

        }
    }
    [DataContract]
    public class KSyncConflict : IDisposable
    {
        [DataMember]
        public KApplyAction Action { get; set; }
        [DataMember]
        public string Description { get; set; }
        [DataMember]
        public bool IsSolve { get; set; }
        public string ViewSort { get; set; }

        public object[] KeyValues { get; set; }
        private string _errorMessage;
        private DataTable _localRows;
        private DataTable _remoteRows;
        private DbSyncStage _stage;
        private DbConflictType _type;
        [DataMember]
        public string ErrorMessage
        {
            get
            {
                return this._errorMessage;
            }
            set
            {
                this._errorMessage = value;
            }
        }
        [DataMember]
        public DataTable LocalChange
        {
            get
            {
                return this._localRows;
            }
            set
            {
                _localRows = value;
            }

        }
        [DataMember]
        public DataTable RemoteChange
        {
            get
            {
                return this._remoteRows;
            }
            set
            {
                _remoteRows = value;
            }
        }
        [DataMember]
        public DbSyncStage Stage
        {
            get
            {
                return this._stage;
            }
            set
            {
                this._stage = value;
            }
        }

        [DataMember]
        public DbConflictType Type
        {
            get
            {
                return this._type;
            }
            set
            {
                this._type = value;
            }
        }

        public KSyncConflict()
        {

        }

        public KSyncConflict(DataTable local, DataTable remote)
        {
            _localRows = local.Copy();
            _remoteRows = remote.Copy();
        }
        public KSyncConflict(string description, DbSyncConflict s)
            : this(KApplyAction.UserManual, description, s)
        {
        }
        public KSyncConflict(ApplyAction action, string description, DbSyncConflict s)
            : this(((KApplyAction)(int)action), description, s)
        {


        }
        public KSyncConflict(KApplyAction action, string description, DbSyncConflict s)
        {
            Description = description;
            _localRows = s.LocalChange.Copy();
            _remoteRows = s.RemoteChange.Copy();
            _stage = s.Stage;
            _type = s.Type;
            ErrorMessage = s.ErrorMessage;
            Action = action;
        }



        #region IDisposable Members

        public void Dispose()
        {
            Description = null;
            _errorMessage = "";
            _localRows.Dispose();
            _remoteRows.Dispose();
            KeyValues = null;
            ViewSort = null;
            Disposed = true;
        }

        #endregion
        bool Disposed;
        ~KSyncConflict()
        {
            if (!Disposed)
                Dispose();
        }
    }
    [DataContract]
    public enum KApplyAction
    {
        [EnumMember]
        Continue = 0,
        [EnumMember]
        RetryApplyingRow = 1,
        [EnumMember]
        RetryWithForceWrite = 2,
        [EnumMember]
        RetryNextSync = 3,
        [EnumMember]
        UserManual = 4,
        [EnumMember]
        Unknown = -1
    }

    public static class SyncExtentsion
    {
        public static DbSyncScopeProgress KClone(this DbSyncScopeProgress d)
        {
            DbSyncScopeProgress progress = new DbSyncScopeProgress();
            foreach (DbSyncTableProgress progress2 in d.TablesProgress)
            {
                progress.TablesProgress.Add(progress2.KClone());
            }
            return progress;

        }
        public static DbSyncTableProgress KClone(this DbSyncTableProgress d)
        {
            DbSyncTableProgress progress = new DbSyncTableProgress(d.TableName);
            progress.Inserts = d.Inserts;
            progress.Updates = d.Updates;
            progress.Deletes = d.Deletes;
            progress.ChangesApplied = d.ChangesApplied;
            progress.ChangesFailed = d.ChangesFailed;
            return progress;
        }
    }

    public class ProxyInfo<T>
    {
        public Stopwatch Ide { get; set; }
        private T _Channel;
        public ChannelFactory<T> ChannelFactory { get; set; }
        public T Channel
        {
            get
            {
                Ide.Reset();
                return _Channel;
            }
            set
            {
                _Channel = value;
                Ide.Reset();
            }
        }

    }
}
